package com.oweight.com2tpc.connect.tcp;

import cn.hutool.core.lang.Console;
import com.oweight.com2tpc.Controller;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Executors;

@Slf4j
public class TCPClient {
	public static Channel channel;
	private static boolean reconnection = false;

	public static void start(Controller controller) {
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		Bootstrap b = new Bootstrap();
		b.group(bossGroup)
			.channel(NioSocketChannel.class)
			.option(ChannelOption.SO_KEEPALIVE, true)
			.handler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					ch.pipeline().addLast(
						new ByteArrayEncoder(),
						new ByteArrayDecoder(),
						new TCPDataHandler(controller)
					);
				}
			});
		try {
			ChannelFuture f = b.connect(Controller.hostStr, Integer.parseInt(Controller.portStr)).sync();
			if (f.isSuccess()) {
				Console.log("Open port: " + Controller.portStr);
				Console.log("Connected success.");
				Controller.connectionSucceeded(controller.tcpStatus, controller.tcpConnect);
				reconnection = false;
			}
			channel = f.channel();
			channel.closeFuture().sync();
		} catch (InterruptedException e) {
			Console.log("Connected failed!", e);
			reconnection = true;
		} finally {
			Console.log("Closing");
			bossGroup.shutdownGracefully();
			Controller.connectionFailed(controller.tcpStatus, null);
			// 自动连接
			Executors.newSingleThreadExecutor().execute(() -> {
				do {
					if (Controller.tcpInitiativeDisconnect) {
						// 用户自行断开连接
						break;
					}
					Console.log("自动重连...");
					try {
						TCPClient.start(controller);
					} catch (Exception e) {
						Console.log("TCP/IP断开连接！");
					}
				} while (reconnection);
			});
		}
	}

	public static void stop() {
		if (channel != null) {
			channel.close();
		}
	}
}
